package com.xyazm.order.statemachine.action.order.create.node;

import com.xyazm.address.domain.dto.AddressDTO;
import com.xyazm.address.domain.param.QueryAddressParam;
import com.xyazm.common.utils.JsonUtil;
import com.xyazm.coupon.domain.dto.UserCouponDTO;
import com.xyazm.coupon.domain.param.QueryUserCouponParam;
import com.xyazm.market.domain.dto.CalculateOrderAmountDTO;
import com.xyazm.order.config.OrderProperties;
import com.xyazm.order.domain.builder.FullOrderData;
import com.xyazm.order.domain.builder.NewOrderBuilder;
import com.xyazm.order.domain.entity.*;
import com.xyazm.order.domain.holder.NewOrderDataHolder;
import com.xyazm.order.domain.param.CreateOrderParam;
import com.xyazm.order.enums.SnapshotTypeEnum;
import com.xyazm.order.remote.AddressRemote;
import com.xyazm.order.remote.CouponRemote;
import com.xyazm.process.engine.process.ProcessContext;
import com.xyazm.process.engine.process.StandardProcessor;
import com.xyazm.product.domain.dto.ProductSkuDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 构建主订单信息节点
 * @author xuyou
 * @date 2023年02月02日 21:13
 */
@Slf4j
@Component
public class CreateOrderMasterBuilderNode extends StandardProcessor {

    @Autowired
    private OrderProperties orderProperties;

    @Autowired
    private AddressRemote addressRemote;

    @Autowired
    private CouponRemote couponRemote;


    @Override
    protected void processInternal(ProcessContext context) {
        CreateOrderParam createOrderParam = context.get("createOrderParam");
        List<ProductSkuDTO> productSkuList = context.get("productSkuList");
        CalculateOrderAmountDTO calculateOrderAmountDTO = context.get("calculateOrderAmountDTO");

        // 1、对sku按照商品类型进行分组
        Map<Integer, List<ProductSkuDTO>> productTypeMap = productSkuList.stream()
                .collect(Collectors.groupingBy(ProductSkuDTO::getProductType));

        // 2、生成主订单
        FullOrderData fullMasterOrderData = addNewMasterOrder(createOrderParam, productSkuList,
                calculateOrderAmountDTO, productTypeMap);

        // 3、封装主订单数据到NewOrderData对象中
        NewOrderDataHolder newOrderDataHolder = new NewOrderDataHolder();
        newOrderDataHolder.appendOrderData(fullMasterOrderData);

        context.set("fullMasterOrderData", fullMasterOrderData);
        context.set("newOrderDataHolder", newOrderDataHolder);
        context.set("productTypeSet", productTypeMap.keySet());
    }



    /**
     * 新增主订单信息订单
     * @author xuyou
     * 2022/5/2 0002 21:25
     * @param createOrderParam 创建订单入参
     * @param productSkuList 商品详细信息
     * @param calculateOrderAmountDTO 计算订单费用信息
     * @return java.lang.Object 全量的订单基础数据
     */
    private FullOrderData addNewMasterOrder(CreateOrderParam createOrderParam,
                                            List<ProductSkuDTO> productSkuList,
                                            CalculateOrderAmountDTO calculateOrderAmountDTO, Map<Integer,
                                            List<ProductSkuDTO>> productTypeMap) {

        NewOrderBuilder newOrderBuilder = new NewOrderBuilder(
                createOrderParam,
                productSkuList,
                calculateOrderAmountDTO,
                orderProperties,
                productTypeMap);
        // 构建操作db锁需要的po对象
        FullOrderData fullOrderData = newOrderBuilder
                .buildOrderInfo()
                .setOrderType()
                .buildOrderItem()
                .addPreSaleInfoToOrderItems()
                .buildOrderDeliveryDetail()
                .buildOrderPaymentDetail()
                .buildOrderAmount()
                .buildOrderAmountDetail()
                .buildOperateLog()
                .buildOrderSnapshot()
                .build();

        // 订单信息
        OrderInfoDO orderInfoDO = fullOrderData.getOrderInfoDO();
        // 订单条目信息
        List<OrderItemDO> orderItemDOList = fullOrderData.getOrderItemDOList();
        // 订单费用信息
        List<OrderAmountDO> orderAmountDOList = fullOrderData.getOrderAmountDOList();

        // 补全地址信息
        OrderDeliveryDetailDO orderDeliveryDetailDO = fullOrderData.getOrderDeliveryDetailDO();
        // 获取用户收货详细地址
        String detailAddress = getDetailAddress(orderDeliveryDetailDO);
        orderDeliveryDetailDO.setDetailAddress(detailAddress);

        // 补全订单状态变更日志
        OrderOperateLogDO orderOperateLogDO = fullOrderData.getOrderOperateLogDO();
        String remark = "创建订单操作0-10";
        orderOperateLogDO.setRemark(remark);

        // 补全订单商品快照信息
        List<OrderSnapshotDO> orderSnapshotDOList = fullOrderData.getOrderSnapshotDOList();
        for (OrderSnapshotDO orderSnapshotDO : orderSnapshotDOList) {
            // 优惠券信息
            if (SnapshotTypeEnum.ORDER_COUPON.getCode().equals(orderSnapshotDO.getSnapshotType())) {
                String couponId = orderInfoDO.getCouponId();
                String userId = orderInfoDO.getUserId();
                QueryUserCouponParam queryUserCouponParam = new QueryUserCouponParam();
                queryUserCouponParam.setCouponId(couponId);
                queryUserCouponParam.setUserId(userId);
                try {
                    // 调用优惠券服务api,查询用户优惠券详情
                    UserCouponDTO userCouponDTO = couponRemote.getUserCoupon(queryUserCouponParam);
                    orderSnapshotDO.setSnapshotJson(JsonUtil.object2Json(userCouponDTO));
                } catch (Exception e) {
                    // 忽略报错
                    orderSnapshotDO.setSnapshotJson(JsonUtil.object2Json(couponId));
                }
            } else if (SnapshotTypeEnum.ORDER_AMOUNT.getCode().equals(orderSnapshotDO.getSnapshotType())) {
                // 订单费用信息
                orderSnapshotDO.setSnapshotJson(JsonUtil.object2Json(orderAmountDOList));
            } else if (SnapshotTypeEnum.ORDER_ITEM.getCode().equals(orderSnapshotDO.getSnapshotType())) {
                // 订单条目信息
                orderSnapshotDO.setSnapshotJson(JsonUtil.object2Json(orderItemDOList));
            }
        }
        return fullOrderData;
    }


    /**
     * 获取用户收货详细地址
     * @author xuyou
     * 2022/5/15 0015 17:26
     * @param orderDeliveryDetailDO 订单配送信息
     * @return java.lang.String 用户下单收货地址
     */
    private String getDetailAddress(OrderDeliveryDetailDO orderDeliveryDetailDO) {
        String provinceCode = orderDeliveryDetailDO.getProvince();
        String cityCode = orderDeliveryDetailDO.getCity();
        String areaCode = orderDeliveryDetailDO.getArea();
        String streetCode = orderDeliveryDetailDO.getStreet();
        QueryAddressParam queryAddressParam = new QueryAddressParam();
        queryAddressParam.setProvinceCode(provinceCode);
        queryAddressParam.setCityCode(cityCode);
        queryAddressParam.setAreaCode(areaCode);
        queryAddressParam.setStreetCode(streetCode);
        // 调用地址服务api-查询行政地址
        AddressDTO addressDTO = null;
        try {
            addressDTO = addressRemote.queryAddress(queryAddressParam);
        } catch (Exception e) {
            log.error("addressRemote.queryAddress error ",e);
        }
        if (addressDTO == null) {
            return orderDeliveryDetailDO.getDetailAddress();
        }
        StringBuilder detailAddress = new StringBuilder();
        if (StringUtils.isNotEmpty(addressDTO.getProvince())) {
            detailAddress.append(addressDTO.getProvince());
        }
        if (StringUtils.isNotEmpty(addressDTO.getCity())) {
            detailAddress.append(addressDTO.getCity());
        }
        if (StringUtils.isNotEmpty(addressDTO.getArea())) {
            detailAddress.append(addressDTO.getArea());
        }
        if (StringUtils.isNotEmpty(addressDTO.getStreet())) {
            detailAddress.append(addressDTO.getStreet());
        }
        if (StringUtils.isNotEmpty(orderDeliveryDetailDO.getDetailAddress())) {
            detailAddress.append(orderDeliveryDetailDO.getDetailAddress());
        }
        return detailAddress.toString();
    }

}
